﻿namespace LM.Negocio.Validadores
{
    using LM.InterfacesFabricas.Interfaces.Repositorios;
    using LM.Negocio.Objetos;
    using System;
    using System.Linq;
    using LM.InterfacesFabricas.Basicos.Enumeradores;

    /// <summary>
    /// Rafael.
    /// Classe que verifica a consistencia do Clientes.
    /// </summary>
    public class ValidadorDeCliente : ValidadorAbastrato
    {
        private Cliente _objetoValidado;

        private IRepositorioDeConsultaDeObjetos<Cliente> _repositorioDeCliente;
        private IRepositorioDeConsultaDeObjetos<Telefone> _repositorioDeTelefone;
        private IRepositorioDeConsultaDeObjetos<Endereco> _repositorioDeEndereco;

        public ValidadorDeCliente(IRepositorioDeConsultaDeObjetos<Cliente> repositorioDeCliente, 
                                  IRepositorioDeConsultaDeObjetos<Telefone> repositorioDeTelefone,
                                  IRepositorioDeConsultaDeObjetos<Endereco> repositorioDeEndereco)
        {
            if (repositorioDeCliente == null)
            {
                throw new ArgumentNullException("repositorioDeCliente");
            }

            if (repositorioDeTelefone == null)
            {
                throw new ArgumentNullException("repositorioDeTelefone");
            }

            if (repositorioDeEndereco == null)
            {
                throw new ArgumentNullException("repositorioDeEndereco");
            }

            _repositorioDeCliente = repositorioDeCliente;
            _repositorioDeTelefone = repositorioDeTelefone;
            _repositorioDeEndereco = repositorioDeEndereco;
        }
        
        public void ValideCadastro(Cliente cliente)
        {
            if (cliente == null)
            {
                throw new ArgumentException("cliente");
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideCpfNaoInformado();
            ValideCnhNaoInformada();
            ValideTipoDoCliente();
            ValideTelefoneNaoInformado();

            ValideClienteJaCadastrado();

            base.GarantaSucesso();
        }

        public void ValideAtualizacao(Cliente cliente)
        {
            if (cliente == null)
            {
                throw new ArgumentException("Clientes");
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideCpfNaoInformado();
            ValideCnhNaoInformada();
            ValideTipoDoCliente();
            ValideTelefoneNaoInformado();

            var validadorTelefone = new ValidadorDeTelefone(_repositorioDeTelefone);

            foreach (var telefone in cliente.Telefones)
            {
                if (validadorTelefone.TelefoneJaCadastrada(telefone))
                {
                    validadorTelefone.ValideAtualizacao(telefone);
                }
                else 
                {
                    validadorTelefone.ValideCadastro(telefone);
                }
            }

            var validadorEndereco = new ValidadorDeEndereco(_repositorioDeEndereco);
            foreach (var endereco in cliente.Endereco)
            {
                if (validadorEndereco.EnderecoJaCadastrado(endereco))
                {
                    validadorEndereco.ValideAtualizacao(endereco);
                }
                else
                {
                    validadorEndereco.ValideCadastro(endereco);
                }
            }
            

            ValideClienteNaoCadastrado();

            base.GarantaSucesso();
        }

        public void ValideExclusao(Cliente cliente)
        {
            if (cliente == null)
            {
                throw new ArgumentException("Clientes");
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideClienteNaoCadastrado();

            base.GarantaSucesso();
        }

        private void ValideCodigoNaoInformado()
        {
            if (_objetoValidado.Codigo == 0)
            {
                AdicioneInconsistencia("Código não informado.");
            }
        }

        private void ValideNomeNaoInformado()
        {
            if (String.IsNullOrWhiteSpace(_objetoValidado.Nome))
        {
                AdicioneInconsistencia("Nome não informado.");
            }
        }

        private void ValideCpfNaoInformado()
        {
            if (_objetoValidado.Cpf == 0) 
            {
                AdicioneInconsistencia("Cpf não Informado.");
            }
        }
        
        private void ValideCnhNaoInformada()
        {
            if (_objetoValidado.Cnh == 0)
            {
                AdicioneInconsistencia("Cnh não informada.");
            }
        }

        private void ValideTipoDoCliente() 
        {
            if (!Enum.IsDefined(typeof(EnumTipoDoCliente), _objetoValidado.TipoDoCliente))
            {
                AdicioneInconsistencia("Tipo do Cliente não informado.");
            }
        }

        private bool ClienteJaCadastrado()
        {
            return _repositorioDeCliente.Consulte(m => m.Codigo == _objetoValidado.Codigo).Any();
        }

        private void ValideClienteJaCadastrado()
        {
            if (ClienteJaCadastrado())
        {
                AdicioneInconsistencia("Já existe uma Clientes cadastrado com o código {0}.", _objetoValidado.Codigo);
            }
        }

        private void ValideTelefoneNaoInformado()
        {
            if (_objetoValidado.Telefones.Count() == 0)
            {
                AdicioneInconsistencia("Nenhum Telefone informado.");
            }
        }

        private void ValideClienteNaoCadastrado()
        {
            if (!ClienteJaCadastrado())
            {
                AdicioneInconsistencia("Clientes com o código {0} não está cadastrado.", _objetoValidado.Codigo);
            }
            }
    }
}
